//
// Created by javier on 3/11/15.
//

#include "datetime.h"
#include <cmath>

void datetime::jd2cal(const double jd, int *y, int *m, double *day_fraq)
{
    //	% JD2CAL  Converts Julian date to calendar date using algorithm
    //	%   from "Practical Ephemeris Calculations" by Oliver Montenbruck
    //	%   (Springer-Verlag, 1989). Must use astronomical year for B.C.
    //	%   dates (2 BC = -1 yr). Non-vectorized version. See also CAL2JD,
    //	%   DOY2JD, GPS2JD, JD2DOW, JD2DOY, JD2GPS, JD2YR, YR2JD.
    //	% Version: 24 Apr 99
    //	% Usage:   [yr, mn, dy]=jd2cal(jd)
    //	% Input:   jd - Julian date
    //	% Output:  yr - year of calendar date
    //	%          mn - month of calendar date
    //	%          dy - day of calendar date (including decimal)
    //
    //	% Copyright (c) 2011, Michael R. Craymer
    //	% All rights reserved.
    //	% Email: mike@craymer.com

    long int a = floor(jd + 0.5);
    long int b, c, d, e, f;
    if (a < 2299161)
        {
            c = a + 1524;
        }
    else
        {
            b = floor(((double)a - 1867216.25) / 36524.25);
            c = a + b - floor((double)b / 4.0) + 1525;
        }
    d = floor(((double)c - 122.1) / 365.25);
    e = floor(365.25 * (double)d);
    f = floor(((double)c - (double)e) / 30.6001);

    *day_fraq = (double)c - (double)e - (double)floor(30.6001 * f) + fmod((jd + 0.5), (double)a);
    *m = f - 1 - 12 * floor((double)f / 14.0);
    *y = d - 4715 - floor((double)(7 + (double)*m) / 10.0);
}

datetime::datetime()
{
    y = 0;
    m = 0;
    d = 0;
    hh = 0;
    mm = 0;
    sec = 0.0;
}

void datetime::gps2date(gpstime *g)
{
    double jd;
    double day_fraq;
    int _y, _m;

    jd = g->gps2jd(0);
    jd2cal(jd, &_y, &_m, &day_fraq);

    y = _y;
    m = _m;
    d = floor(day_fraq);
    double hour_fraq = (day_fraq - (double)d) * 24.0;
    hh = floor(hour_fraq);
    double minute_fraq = (hour_fraq - hh) * 60.0;
    mm = floor(minute_fraq);
    sec = (minute_fraq - (double)mm) * 60.0;
    sec = round(sec * 1000.0) / 1000.0;
}

gpstime datetime::date2gps()
{
    gpstime g;
    int doy[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
    int ye;
    int de;
    int lpdays;

    ye = y - 1980;

    // Compute the number of leap days since Jan 5/Jan 6, 1980.
    lpdays = ye / 4 + 1;
    if ((ye % 4) == 0)
        {
            if (m <= 2)
                {
                    lpdays--;
                }
        }

    // Compute the number of days elapsed since Jan 5/Jan 6, 1980.
    de = ye * 365 + doy[m - 1] + d + lpdays - 6;

    // Convert time to GPS weeks and seconds.
    g.week = de / 7;
    g.sec = (double)(de % 7) * 86400.0 + hh * 3600.0 + mm * 60.0 + sec;

    //	printf("ORIGEN: y %d, m %d, d %d, h %d, m %d, s %f \n", t->y, t->m, t->d, t->hh, t->mm, t->sec);
    //	printf("week %d, sec %f \n", g->week, g->sec);

    return g;
}
